package com.tupu.service.impl.dispatch;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tupu.entity.dispatch.SignalmissingData;
import com.tupu.entity.dto.T0122IalmFactionDTO;
import com.tupu.mapper.ocs.T0122IalmFactionMapper;
import com.tupu.service.dispatch.SignalmissingDataService;
import com.tupu.mapper.dispatch.SignalmissingDataMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.text.DecimalFormat;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 15702
 * @description 针对表【tb_signalmissing_data】的数据库操作Service实现
 * @createDate 2023-11-22 17:32:20
 */
@Slf4j
@Service
public class SignalmissingDataServiceImpl extends ServiceImpl<SignalmissingDataMapper, SignalmissingData>
        implements SignalmissingDataService {

    public static final DateTimeFormatter dfH = DateTimeFormatter.ofPattern("yyyyMMddHH");
    public static final DateTimeFormatter dfYMDHMS = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
    public static final DateTimeFormatter dfD = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final DateTimeFormatter dfHMS = DateTimeFormatter.ofPattern("HHmmssSSS");
    public static final DateTimeFormatter dfYDNHMS = new DateTimeFormatterBuilder().appendPattern("yyyyMMddHHmmss")
            .appendValue(ChronoField.MILLI_OF_SECOND, 3).toFormatter();

    @Autowired
    private T0122IalmFactionMapper t0122IalmFactionMapper;

    @Override
    public void findMissingSignal(LocalDateTime startTime, LocalDateTime endTime) {
        Duration duration = Duration.between(startTime, endTime);
        long days = duration.toDays();
        if (days > 5) {
            for (long i = 0; i < days; i++) {
                LocalDateTime startTime1 = startTime.plusDays(i);
                LocalDateTime endTime1 = startTime.plusDays(i + 1);
                log.info("分批计算信号缺失 startTime:{} endTime:{}", startTime1, endTime1);
                this.doFindMissingSignal(startTime1, endTime1);
            }
        } else {
            this.doFindMissingSignal(startTime, endTime);
        }
    }

    @Override
    public void doFindMissingSignal(LocalDateTime startTime, LocalDateTime endTime) {
        String startTimeYmd = startTime.format(dfD);
        String startTimeHms = startTime.format(dfHMS);
        String endTimeYmd = endTime.format(dfD);
        String endTimeHms = endTime.format(dfHMS);
        List<T0122IalmFactionDTO> list = t0122IalmFactionMapper.getList(startTimeYmd, startTimeHms, endTimeYmd, endTimeHms);
        Map<String, T0122IalmFactionDTO> eventMap = new HashMap<>();
        list.forEach(item -> {
            String key = item.getC0122FCode() + item.getC0122PointId() + item.getC0122EventType();
            eventMap.compute(key, (k, v) -> {
                if (item.getC0122EventType() != null && item.getC0122EventType() == 1001) {
                    // 1001-开关变位 0:断开 1:闭合
                    if (item.getC0122ActionType() != null) {
                        if (item.getC0122ActionType() == 0) {
                            // 0:断开
                            return item;
                        } else if (item.getC0122ActionType() == 1) {
                            // 1:闭合
                            // 获取开始事件
                            if (v != null && v.getC0122ActionType() != null && v.getC0122ActionType() == 0) {
                                // 存在开始事件，则抵消 返回null删除开始事件
                                return null;
                            } else {
                                // 不存在则添加该闭合事件
                                return item;
                            }
                        }
                    }
                } else if (item.getC0122EventType() != null && item.getC0122EventType() == 1002) {
                    // 1002-保护信息  1:动作 0:恢复
                    if (item.getC0122ActionType() == 1) {
                        // 1:动作
                        return item;
                    } else if (item.getC0122ActionType() == 0) {
                        // 0:恢复
                        // 获取开始事件
                        if (v != null && v.getC0122ActionType() != null && v.getC0122ActionType() == 1) {
                            // 存在开始事件，则抵消 返回null删除开始事件
                            return null;
                        } else {
                            // 不存在则添加该闭合事件
                            return item;
                        }
                    }
                }
                // 不匹配或者动作为null 添加到Map
                return item;
            });
        });
        List<SignalmissingData> signalmissingDataList = eventMap.values().stream().map(item -> {
            SignalmissingData signalmissingData = new SignalmissingData();
            signalmissingData.setSignalId(item.getC0122FCode() + item.getC0122PointId() + "_" + item.getC0122EventType() + "_" + item.getC0122ActionType());
            signalmissingData.setStation(item.getC0003StationDesc());

            signalmissingData.setDeviceName(item.getC1211Devdesc());
            signalmissingData.setDeviceType(item.getC1216Devtypedesc());
            signalmissingData.setDeviceId(item.getC1211Devid());
            signalmissingData.setPointId(item.getC0122PointId());
            signalmissingData.setEventType(item.getC0122EventType());
            signalmissingData.setActionType(item.getC0122ActionType());
            signalmissingData.setDataSourceType("事件");
            signalmissingData.setCreateTime(LocalDateTime.now());

            // 2023/08/02 12:00:20           保护信号  南海站                35kV码头乙线362差动保护动作   动作
            String[] ss = item.getC0122ActionDesc().split("\\s+");
            try {
                if (ss.length >= 4) {
                    String timeStr = ss[0].trim() + " " + ss[1].trim();
                    String station = ss[3].trim();
                    String desc = ss[4].trim();
                    LocalDateTime time = LocalDateTime.parse(timeStr, dfYMDHMS);
                    signalmissingData.setTime(time);
                    signalmissingData.setSignalDesc(desc);
                    if (StringUtils.isEmpty(signalmissingData.getStation())) {
                        signalmissingData.setStation(station);
                    }
                    if (ss.length >= 5) {
                        String action = ss[5];
                        signalmissingData.setAction(action);
                        String missingDesc = desc + " " + action;
                        if (item.getC0122EventType() != null && item.getC0122EventType() == 1001) {
                            // 1001-开关变位 0:断开 1:闭合
                            if (item.getC0122ActionType() != null) {
                                if (item.getC0122ActionType() == 0) {
                                    // 0:断开
                                    missingDesc = desc + "断开 ，无相关闭合信息";
                                } else if (item.getC0122ActionType() == 1) {
                                    // 1:闭合
                                    missingDesc = desc + "闭合 ，无相关断开信息";
                                }
                            }
                        } else if (item.getC0122EventType() != null && item.getC0122EventType() == 1002) {
                            // 1002-保护信息  1:动作 0:恢复
                            if (item.getC0122ActionType() == 1) {
                                // 1:动作
                                missingDesc = desc + "动作 ，无相关恢复信息";
                            } else if (item.getC0122ActionType() == 0) {
                                // 0:恢复
                                missingDesc = desc + " 恢复 ，无相关动作信息";
                            }
                        }
                        signalmissingData.setMissingDesc(missingDesc);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            return signalmissingData;
        }).collect(Collectors.toList());
        this.saveOrUpdateBatch(signalmissingDataList);
    }

    @Override
    public Map<String, Object> deviceTypePercentage(String station, LocalDateTime startTime, LocalDateTime endTime, String deviceType) {
        Map<String, Object> result = new LinkedHashMap<>();
        List<Map<String, Object>> query = this.baseMapper.deviceTypePercentage(station, startTime, endTime, deviceType);
        if (query.size() == 1 && StringUtils.isNotEmpty(deviceType)) {
            Map<String, Object> map = new HashMap<>();
            map.put("device_type", deviceType);
            map.put("sum", 0L);
            query.add(map);
        }
        Map<String, Long> map = query.stream().collect(Collectors.toMap(i -> i.get("device_type").toString(), i -> (Long) i.get("sum"), (pre, cur) -> cur, LinkedHashMap::new));
        float total = Optional.ofNullable(map.get("全部")).map(t -> t * 1.0F).orElse(0F);
        map.forEach((k, v) -> {
            if (!k.equals("全部")) {
                DecimalFormat decimalFormat = new DecimalFormat("#0.00%");
                String format = total != 0F ? decimalFormat.format(Optional.ofNullable(map.get(k)).orElse(0L) / total) : "0";
                result.put(k, format);
            }
        });
        return result;
    }

    @Override
    public Map<String, Object> stationPercentage(String deviceType, LocalDateTime startTime, LocalDateTime endTime, String station) {
        Map<String, Object> result = new LinkedHashMap<>();
        List<Map<String, Object>> query = this.baseMapper.stationPercentage(deviceType, startTime, endTime, station);
        if (query.size() == 1 && StringUtils.isNotEmpty(station)) {
            Map<String, Object> map = new HashMap<>();
            map.put("station", station);
            map.put("sum", 0L);
            query.add(map);
        }
        Map<String, Long> map = query.stream().collect(Collectors.toMap(i -> i.get("station").toString(), i -> (Long) i.get("sum"), (pre, cur) -> cur, LinkedHashMap::new));
        float total = Optional.ofNullable(map.get("全部")).map(t -> t * 1.0F).orElse(0F);
        map.forEach((k, v) -> {
            if (!k.equals("全部")) {
                DecimalFormat decimalFormat = new DecimalFormat("#0.00%");
                String format = total != 0F ? decimalFormat.format(Optional.ofNullable(map.get(k)).orElse(0L) / total) : "0";
                result.put(k, format);
            }
        });
        return result;
    }

    @Override
    public Page<SignalmissingData> pageMassage(String deviceName, String deviceType, String station, LocalDateTime startTime, LocalDateTime endTime, Long page, Long size) {
        QueryWrapper<SignalmissingData> queryWrapper = new QueryWrapper<>();
        Page<SignalmissingData> info = new Page<>(page, size);
        if (StringUtils.isNotEmpty(deviceName)) {
            queryWrapper.like("device_name", deviceName);
        }
        if (StringUtils.isNotEmpty(station)) {
            queryWrapper.eq("station", station);
        }
        if (StringUtils.isNotEmpty(deviceType)) {
            queryWrapper.eq("device_type", deviceType);
        }
        if (startTime != null) {
            queryWrapper.ge("time", startTime);
        }
        if (endTime != null) {
            queryWrapper.le("time", endTime);
        }
        queryWrapper.orderByDesc("time");
        baseMapper.selectPage(info, queryWrapper);
        return info;
    }

    @Override
    public List<Map<String, Object>> signalOmissionPointTableMsgStationTop5(String deviceType, LocalDateTime startTime, LocalDateTime endTime) {
        return this.baseMapper.signalOmissionPointTableMsgStationTop5(deviceType, startTime, endTime);

    }

    @Scheduled(cron = "0 0/15 * * * ? ")
    public void scheduledCount() {
        // 避免系统时间不一致查不到数据 每15分钟查询50分钟数据
        //LocalDateTime startTime = LocalDateTime.now().minusMinutes(50);
        //查询前一个月数据
        LocalDateTime startTime = LocalDateTime.now().minusMonths(1);
        // 避免系统时间不一致查不到数据
        LocalDateTime endTime = LocalDateTime.now().plusMinutes(50);
        log.info("开始信号缺失分析");
        this.findMissingSignal(startTime, endTime);
        log.info("信号缺失分析完成");
    }
}




